package org.xqp.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.xqp.basic.exception.MyException;
import org.xqp.order.domain.OrderPet;
import org.xqp.order.domain.OrderPetDetail;
import org.xqp.order.mapper.OrderPetDetailMapper;
import org.xqp.order.mapper.OrderPetMapper;
import org.xqp.pay.domain.PayAlipayInfo;
import org.xqp.pay.domain.PayBill;
import org.xqp.pay.domain.PayFlow;
import org.xqp.pay.dto.AlipayNotifyDto;
import org.xqp.pay.mapper.PayAlipayInfoMapper;
import org.xqp.pay.mapper.PayBillMapper;
import org.xqp.pay.mapper.PayFlowMapper;
import org.xqp.pay.service.IPayService;
import org.xqp.pet.domain.Pet;
import org.xqp.pet.mapper.PetMapper;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class PayServiceImpl  implements IPayService {

    @Autowired
    private PayAlipayInfoMapper alipayInfoMapper;
    @Autowired
    private PayBillMapper payBillMapper ;
    @Autowired
    private PayFlowMapper payFlowMapper;
    @Autowired
    private OrderPetMapper orderPetMapper ;
    @Autowired
    private OrderPetDetailMapper orderPetDetailMapper;
    @Autowired
    private PetMapper petMapper;


    //支付申请
    @Override
    public String applyPay(String orderNo) {
        //1.判断参数
        if(!StringUtils.hasLength(orderNo)){
            throw new MyException("非法请求");
        }

        //2.加载支付宝配置
        PayAlipayInfo alipayInfo = alipayInfoMapper.selectFirst();

        if(alipayInfo == null){
            throw new MyException("无效的支付宝配置，请联系管理员");
        }

        //3.查询支付单
        PayBill payBill = payBillMapper.selectByNo(orderNo);
        if(payBill == null){
            throw new MyException("非法请求");
        }
        //4.发起支付请求
        //  1. 设置参数（全局只需设置一次）
        Factory.setOptions(alipayInfo.getOptions());

        try {
            // 2. 发起API调用:电脑网站
            //String returnUrl = String.format("http://127.0.0.1/pay-success.html?orderNo=%s",orderNo);
            //String returnUrl = String.format(alipayInfo.getReturnUrl(),orderNo);

            AlipayTradePagePayResponse response = Factory.Payment.Page()
                    .pay(payBill.getDigest(), //标题
                         payBill.getUnionPaySn(), //单号
                         payBill.getMoney().toString(),  //金额
                            "http://127.0.0.1:80");//同步回调地址

            // 3. 处理响应或异常
            System.out.println("----------------------------------------");
            System.out.println(response.body);
            System.out.println("----------------------------------------");
            if (ResponseChecker.success(response)) {
                System.out.println("调用成功");
                //5.处理结果
                return response.body;
            } else {
                System.err.println("调用失败，原因：" );
            }

        } catch (Exception e) {
            System.err.println("调用遭遇异常，原因：" + e.getMessage());
            throw new RuntimeException(e.getMessage(), e);
        }

        return "支付申请失败";
    }

//    /**
//     * 支付结果处理
//     * 1.校验参数
//     * 2.验证签名
//     * 3.防止支付结果重复处理 ,支付宝会回调N次
//     *                      - 幂等性处理：调用N次和调用1次的结果一样
//     * 3.保存支付流水PayFlow
//     * 4.修改支付单状态PayBill
//     * 5.修改业务单状态OrderPet
//     * 6.如果是失败，宠物库存退回
//     *
//     * @param dto ：支付网关返回的参数
//     */
//    @Override
//    public String alipayNotify(AlipayNotifyDto dto) {
//        //* 1.校验参数
//        //* 2.验证签名========================================================================
//
//        //把结果DTO转成HashMap用作签名参数
//        //... ... 接收到的所有参数放入一个Map中
//        //把对象转成JSON字符串
//        String JSONStr = JSON.toJSONString(dto);
//        //把JSON字符串转成Map
//        Map<String,String> parameters = JSON.parseObject(JSONStr, Map.class);
//
//        //支付宝的配置
//        PayAlipayInfo alipayInfo = alipayInfoMapper.selectFirst();
//        //Factory.setOptions(alipayInfo.getOptions());
//        try {
//            Boolean verifySignSuccess = Factory.Payment.Common().verifyNotify(parameters);
//            if(!verifySignSuccess){
//                System.out.println("验证签名失败...");
//                return "fail";
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        //判断结果========================================================================
//        //判断订单号，金额是否一致
//        String out_trade_no = dto.getOut_trade_no();
//        if(!StringUtils.hasLength(out_trade_no)){
//            System.out.println("无效的单号...");
//            return "fail";
//        }
//        PayBill payBill = payBillMapper.selectByNo(out_trade_no);
//        if(payBill == null){
//            System.out.println("无效的单号...");
//            return "fail";
//        }
//
//        //* 3.防止支付结果重复处理 ,支付宝会回调N次
//        //*                      - 幂等性处理：调用N次和调用1次的结果一样
//        if(payBill.getState().intValue() != PayBill.SATET_WAIT_PAY){
//            //支付已经被处理
//            System.out.println("订单号已经被处理...");
//            return "success";
//        }
//
//        //对比金额
//        BigDecimal amount = new BigDecimal(dto.getTotal_amount());
//        if(payBill.getMoney().compareTo(amount) != 0){
//            System.out.println("无效的金额...");
//            return "fail";
//        }
//
//
//        String app_id = dto.getApp_id();
//        if(!StringUtils.hasLength(app_id) || !app_id.equals(alipayInfo.getAppid())){
//            System.out.println("无效的APPID...");
//            return "fail";
//        }
//
//        //* 3.保存支付流水PayFlow========================================================================
//        PayFlow payFlow = new PayFlow();
//        BeanUtils.copyProperties(dto, payFlow);
//        payFlowMapper.add(payFlow);
//
//        //* 4.修改支付单状态PayBill
//        if(dto.isTradeWit()){
//            System.out.println("支付中，不处理...");
//            return "fail";
//        }
//
//        //业务单========================================================================
//        OrderPet orderPet = orderPetMapper.selectByOrderNo(out_trade_no);
//
//        /**
//        List<Long> petIds = new ArrayList<>(details.size());
//        details.forEach(detail->{
//            petIds.add(detail.getPetId());
//        });
//        */
//
//        if(orderPet == null){
//            System.out.println("无效的单号...");
//            return "fail";
//        }
//        //订单明细
//        List<OrderPetDetail> details =  orderPetDetailMapper.selectByOrderNo(out_trade_no);
//        //JAVA 1.8 : 宠物ID
//        List<Long> petIds = details.stream().map(detail -> detail.getPetId()).collect(Collectors.toList());
//        //查询所有宠物,这里查询的上线
//        List<Pet> pets = petMapper.batchSelectByIds(petIds, Pet.STATE_ONLINE);
//
//        //支付成功，失败，超时
//        if(dto.isTradeSuccess()){
//            //成功
//            payBill.setState(PayBill.SATET_SUCCESS_PAY);
//            //* 5.修改业务单状态OrderPet
//            //支付成功，待发货
//            orderPet.setState(OrderPet.STATE_SUCCESS_PAY);
//
//        }else if(dto.isTradeExpire()){
//            //超时
//            payBill.setState(PayBill.SATET_OUTTIME_OR_RETURN);
//            orderPet.setState(OrderPet.STATE_PAY_OUTTIME_CANCEL);
//            //* 6.如果是失败，宠物库存退回
//            pets.forEach(pet -> {
//                //严格来说应该加  订单明细中的count
//                pet.setStore_number(pet.getStore_number()+1);
//                petMapper.update(pet);
//            });
//        }else{
//            System.out.println("未知的交易状态");
//            return "fail";
//        }
//        //最后支付处理时间
//        payBill.setLastPayTime(new Date());
//        payBillMapper.update(payBill);
//        orderPetMapper.update(orderPet);
//
//        return "success";
//    }
}
